package com.liuyjy.exception.config;

import com.liuyjy.core.entity.Result;
import com.liuyjy.core.enums.ResultCodeEnum;
import com.liuyjy.core.exception.AppException;
import com.liuyjy.core.exception.BaseException;
import com.liuyjy.core.exception.BusinessException;
import com.liuyjy.core.exception.RemoteRpcException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;


/**
 * @Author liuyjy
 * @Date 2020/4/17 13:15
 * @Description: 前端报文返回方法
 **/
@Slf4j
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {


    //处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常，详情继续往下看代码
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public Result<?> bindExceptionHandler(BindException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        log.error("BindException:{}", message);
        return Result.generate(ResultCodeEnum.SYSTEM_ERROR.code, message);
    }

    //处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public Result<?> constraintViolationExceptionHandler(ConstraintViolationException e) {
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        log.error("ConstraintViolationException:{}", message);
        return Result.generate(ResultCodeEnum.SYSTEM_ERROR.code, message);
    }

    //处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常。
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Result<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        log.error("MethodArgumentNotValidException:{}", message);
        return Result.generate(ResultCodeEnum.SYSTEM_ERROR.code, message);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public Result<?> MissingServletRequestParameterExceptionHandler(MissingServletRequestParameterException e) {
        //String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        log.error("MethodArgumentNotValidException:{}", e.getMessage());
        return Result.generate(ResultCodeEnum.SYSTEM_ERROR.code, e.getMessage());
    }

//    @ExceptionHandler({BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
//    public Result bindExceptionHandler(Exception e) {
//        log.error("参数验证异常！原因是:", e);
//        return ValidationUtil.createValidMsgOld(e);
//    }

    /**
     * 拦截自定义异常
     *
     */
    @ExceptionHandler({BaseException.class, RemoteRpcException.class, AppException.class, BusinessException.class})
    public Result<?> exceptionHandler(BaseException ex) {
        log.error("BaseException:{}", ex.toString());
        return Result.generate(ex.getCode(), ex.getMsg());
    }

    /**
     * 拦截所有错误
     */
    @ExceptionHandler(Exception.class)
    public Result<?> exHandler(Exception ex) {
        if ("org.apache.catalina.connector.ClientAbortException".equals(ex.getClass().getName())) {
            log.error("发生clientAbortException");
            return null;
        }
        log.error("系统错误:", ex);
        return Result.generate(ResultCodeEnum.SERVER_ERROR);
    }

}
